'use strict';

const path = require('path');
const semver = require('semver');
const colors = require('colors/safe');
const userHome = require('user-home');
const pathExists = require('path-exists').sync;
const commander = require('commander');

const log = require('@jay-cli-dev/log');
const exec = require('@jay-cli-dev/exec');
const { getNpmSemverVersion } = require('@jay-cli-dev/get-npm-info');

const pkg = require('../package.json');
const constant = require('./const');

const program = new commander.Command();

async function core() {
    try {
        // 执行脚手架准备流程
        await prepare();

        // 执行脚手架命令注册
        registerCommand();
    } catch (e) {
        log.error(e.message);
        if (program.opts().debug){ // debug模式下，打印调用栈
            console.log(e);
        }
    }
};

async function prepare() {
    checkPkgVersion(); // 检查版本号
    checkRoot(); // 检查root启动
    checkUserHome(); // 检查用户主目录
    checkEnv(); // 检查环境变量
    await checkGlobalUpdate(); // 检查是否需要全局更新
}

function checkPkgVersion() {
    log.notice('cli', pkg.version);
}


function checkRoot() {
    const rootCheck = require('root-check');
    rootCheck();
}

function checkUserHome() {
    if (!userHome || !pathExists(userHome)) {
        throw new Error(colors.red('当前登陆用户主目录不存在'));
    }
}

function checkEnv() {
    const dotEnv = require('dotenv');

    // 获取环境变量配置文件路径
    const dotenvPath = path.resolve(userHome, '.env'); 

    // 路径存在，则配置dotEnv为该路径，便于dotenv将环境变量文件中的配置注入到process.env，详见dotenv文档
    if (pathExists(dotenvPath)) { 
        dotEnv.config({
            path: dotenvPath
        });
    }

    // 处理默认环境变量
    createDefaultConfig();
}

function createDefaultConfig() {
    // 脚手架缓存目录，默认值为constant.DEFAULT_CLI_HOME，可通过命令修改此路径
    process.env.CLI_HOME_PATH = path.join(userHome, process.env.CLI_HOME || constant.DEFAULT_CLI_HOME);;
}


async function checkGlobalUpdate() {
    // 1、获取当前版本号和模块名
    const currentVersion = pkg.version;
    const npmName = pkg.name;

    // 2、获取最新的版本号，提示用户更新到该版本
    const lastVersion = await getNpmSemverVersion(currentVersion, npmName);
    if (lastVersion && semver.gt(lastVersion, currentVersion)) {
        log.warn('更新提示', colors.yellow(`请手动更新 ${npmName} ，当前版本：${currentVersion}，最新版本：${lastVersion}
        更新命令：npm install -g ${npmName}`));
    }
}

// 命令注册
function registerCommand() {
    program
        .name(Object.keys(pkg.bin)[0])
        .usage('<command> [options]')
        .version(pkg.version)
        .option('-d, --debug', '是否开启调试模式', false)
        .option('-tp, --targetPath <targetPath>', '是否指定本地调试文件路径', '');

    // 注册 init 命令
    program
        .command('init [projectName]')
        .option('-f, --force', '是否强制初始化项目', false)
        .action(exec);

    // 开启debug模式
    program.on('option:debug', () => {
        if (program.opts().debug) {
            process.env.LOG_LEVEL = 'verbose';
        } else {
            process.env.LOG_LEVEL = 'info';
        }
        log.level = process.env.LOG_LEVEL;
    })

    // 指定targetPath
    program.on('option:targetPath', () => {
        process.env.CLI_TARGET_PATH = program.opts().targetPath;
    })

    // 对未知命令的监听
    program.on('command:*', (obj) => {
        const availableCommands = program.commands.map(cmd => cmd.name());
        console.log(colors.red('未知的命令：' + obj[0]));
        if (availableCommands.length > 0) {
            console.log(colors.red('可用命令：' + availableCommands.join(',')));
        }
    })
    
    // 解析参数（否则脚手架不会生效）
    program.parse(process.argv);

    // 仅输入 jay-cli-dev 或 jay-cli-dev -d 时，打印帮助信息
    if (program.args && program.args.length < 1) {
        program.outputHelp();
    }
}

module.exports = core;